package com.symaster.backups.frame.element.menu;

import com.symaster.backups.util.TimeUtil;
import lombok.Getter;
import lombok.Setter;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author yinmiao
 * @version 2023/12/4
 */
public class TopMenu extends JComponent implements ActionListener {

    final int barHeight = 3;

    private final Set<ChangeListener> changeListeners = new HashSet<>();
    final IndexData indexData = new IndexData();
    final MotionData motionData = new MotionData();
    private final PaintRunnable paintRunnable;

    @Getter
    @Setter
    private int itemWidth = 80;
    private int menuItemIndex = 0;

    public TopMenu() {
        this.paintRunnable = new PaintRunnable(this);
        Bar bar = new Bar();
        bar.setBackground(new Color(64, 158, 255));
        this.add(bar);
        this.setLayout(new TopMenuLayout());
    }

    public void addItem(Item item) {
        MenuItem menuItem = new MenuItem(menuItemIndex, item.label);
        menuItem.addActionListener(this);
        menuItem.setItem(item);
        add(menuItem);
        menuItemIndex++;
    }

    public Item getItem(int index) {
        for (Component component : getComponents()) {
            if (component instanceof MenuItem menuItem) {
                if (menuItem.getIndex() == index) {
                    return menuItem.getItem();
                }
            }
        }
        return null;
    }

    public void addChangeListener(ChangeListener l) {
        changeListeners.add(l);
    }

    @Override
    public void paint(Graphics g) {
        doLayout();
        super.paint(g);
        drawSeparator(g);

        if (indexData.selectIndex != indexData.selectNewIndex) {
            SwingUtilities.invokeLater(paintRunnable);
        }
    }

    private void drawSeparator(Graphics g) {
        g.setColor(new Color(225, 225, 225));

        List<MenuItem> collect = Arrays.stream(getComponents())
                .filter(e -> e instanceof MenuItem)
                .map(e -> ((MenuItem) e))
                .toList();

        for (int i = 0; i < collect.size(); i++) {
            if (i < collect.size() - 1) {
                MenuItem menuItem = collect.get(i);
                g.fillRect(menuItem.getX() + menuItem.getWidth(), 2, 1, getHeight() - 6);
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof MenuItem source) {

            if (indexData.selectNewIndex == indexData.selectIndex && source.getIndex() != indexData.selectIndex) {
                indexData.selectIndexCheckStartTime = TimeUtil.floatTime();
                indexData.selectNewIndex = source.getIndex();
                SwingUtilities.invokeLater(paintRunnable);

                for (ChangeListener changeListener : changeListeners) {
                    changeListener.menuChange(source.getItem().key, source.getIndex());
                }
            }
        }
    }

    public interface ChangeListener {
        void menuChange(String key, int index);
    }

    @Getter
    public static class Item {
        private final String key;
        private final String label;

        public Item(String key, String label) {
            this.key = key;
            this.label = label;
        }
    }

    static class IndexData {
        public int selectIndex = 0;
        public int selectNewIndex = 0;
        public boolean selectIndexCheck = false;
        public Float selectIndexCheckStartTime;
    }

    static class MotionData {
        public Integer mouseMotionIndex;
    }

    static class PaintRunnable implements Runnable {
        private final TopMenu topMenu;

        public PaintRunnable(TopMenu topMenu) {
            this.topMenu = topMenu;
        }

        @Override
        public void run() {
            topMenu.repaint();
        }
    }

}
